package com.yupi.springbootinit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.constant.OrderType;
import com.yupi.springbootinit.exception.BusinessException;
import com.yupi.springbootinit.exception.ThrowUtils;
import com.yupi.springbootinit.mapper.SalesOrderMapper;
import com.yupi.springbootinit.model.dto.salesorder.SalesOrderQueryRequest;
import com.yupi.springbootinit.model.entity.SalesOrder;
import com.yupi.springbootinit.model.entity.SalesOrderItem;
import com.yupi.springbootinit.model.vo.CountItemVO;
import com.yupi.springbootinit.model.vo.SalesOrderItemVO;
import com.yupi.springbootinit.model.vo.SalesOrderVO;
import com.yupi.springbootinit.service.AttachmentService;
import com.yupi.springbootinit.service.OutboxService;
import com.yupi.springbootinit.service.SalesOrderItemService;
import com.yupi.springbootinit.service.SalesOrderService;
import com.yupi.springbootinit.statemachine.enums.OrderStateEnum;
import com.yupi.springbootinit.statemachine.mapping.OrderStatusMapper;
import com.yupi.springbootinit.utils.SqlUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单服务实现（优化版）
 */
@Service
@Slf4j
public class SalesOrderServiceImpl extends ServiceImpl<SalesOrderMapper, SalesOrder> implements SalesOrderService {

    @Resource
    private SalesOrderMapper salesOrderMapper;

    @Resource
    private SalesOrderItemService salesOrderItemService;

    @Resource
    private AttachmentService attachmentService;

    @Resource
    private OutboxService outboxService;

    @Override
    public void validSalesOrder(SalesOrder salesOrder, boolean add, List<SalesOrderItem> items) {
        if (salesOrder == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "订单信息不能为空");
        }

        // 订单明细必填
        if (items == null || items.isEmpty()) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "订单明细不能为空，至少包含一个产品");
        }

        String orderType = StringUtils.defaultIfBlank(salesOrder.getOrderType(), OrderType.SALES.getCode());
        String orderNumber = salesOrder.getOrderNumber();
        String customerName = salesOrder.getCustomerName();
        BigDecimal totalAmount = salesOrder.getTotalAmount();
        Date dueDate = salesOrder.getDueDate();

        // 新增时的必填项校验
        if (add) {

            ThrowUtils.throwIf(ObjectUtils.isEmpty(dueDate),
                    ErrorCode.PARAMS_ERROR, "交付日期不能为空");

            // 销售订单需要校验总金额
            if (OrderType.SALES.getCode().equals(orderType)) {
                if (totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) <= 0) {
                    // 尝试从明细计算总金额
                    BigDecimal calculatedTotal = items.stream()
                            .map(item -> item.getAmount() != null ? item.getAmount() : BigDecimal.ZERO)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    ThrowUtils.throwIf(calculatedTotal.compareTo(BigDecimal.ZERO) <= 0,
                            ErrorCode.PARAMS_ERROR, "订单总金额必须大于0");
                }
            }
        }

        // 订单号校验
        if (StringUtils.isNotBlank(orderNumber)) {
            ThrowUtils.throwIf(orderNumber.length() > 50, ErrorCode.PARAMS_ERROR, "订单号过长");
            if (add) {
                SalesOrder existOrder = salesOrderMapper.selectByOrderNumber(orderNumber);
                ThrowUtils.throwIf(existOrder != null, ErrorCode.PARAMS_ERROR, "订单号已存在");
            }
        }

        // 校验订单明细
        for (int i = 0; i < items.size(); i++) {
            SalesOrderItem item = items.get(i);
            // 产品信息必填
            ThrowUtils.throwIf(StringUtils.isAnyBlank(item.getProductCode(), item.getProductName()),
                    ErrorCode.PARAMS_ERROR, String.format("第%d个产品的料号和名称不能为空", i + 1));
            // 数量必填且大于0
            ThrowUtils.throwIf(item.getQuantity() == null || item.getQuantity() <= 0,
                    ErrorCode.PARAMS_ERROR, String.format("第%d个产品的数量必须大于0", i + 1));
            // 字段长度校验
            ThrowUtils.throwIf(item.getProductCode().length() > 100,
                    ErrorCode.PARAMS_ERROR, String.format("第%d个产品的料号过长", i + 1));
            ThrowUtils.throwIf(item.getProductName().length() > 200,
                    ErrorCode.PARAMS_ERROR, String.format("第%d个产品的名称过长", i + 1));
            if (StringUtils.isNotBlank(item.getSpecification())) {
                ThrowUtils.throwIf(item.getSpecification().length() > 200,
                        ErrorCode.PARAMS_ERROR, String.format("第%d个产品的规格型号过长", i + 1));
            }
        }

        // 其他字段校验
        if (StringUtils.isNotBlank(customerName)) {
            ThrowUtils.throwIf(customerName.length() > 200, ErrorCode.PARAMS_ERROR, "客户名称过长");
        }
        if (totalAmount != null) {
            ThrowUtils.throwIf(totalAmount.compareTo(BigDecimal.ZERO) <= 0,
                    ErrorCode.PARAMS_ERROR, "订单总金额必须大于0");
        }
        if (dueDate != null) {
            ThrowUtils.throwIf(dueDate.before(new Date()),
                    ErrorCode.PARAMS_ERROR, "交付日期不能早于当前日期");
        }
    }

    @Override
    public QueryWrapper<SalesOrder> getQueryWrapper(SalesOrderQueryRequest req) {
        QueryWrapper<SalesOrder> qw = new QueryWrapper<>();
        if (req == null) {
            return qw;
        }

        String orderType = req.getOrderType();
        String orderNumber = req.getOrderNumber();
        String contractNumber = req.getContractNumber();
        String productCode = req.getProductCode();
        String productName = req.getProductName();
        String customerName = req.getCustomerName();
        String orderStatus = req.getOrderStatus();
        String urgencyLevel = req.getUrgencyLevel();
        Integer isCustomerSecret = req.getIsCustomerSecret();
        Date deliveryDateStart = req.getDeliveryDateStart();
        Date deliveryDateEnd = req.getDeliveryDateEnd();
        Long createdBy = req.getCreatedBy();
        Date createTimeStart = req.getCreateTimeStart();
        Date createTimeEnd = req.getCreateTimeEnd();
        String sortField = req.getSortField();
        String sortOrder = req.getSortOrder();

        // 订单类型过滤
        if (StringUtils.isNotBlank(orderType) && !"ALL".equalsIgnoreCase(orderType)) {
            qw.eq("orderType", orderType);
        }

        // 基本字段查询
        qw.like(StringUtils.isNotBlank(orderNumber), "orderNumber", orderNumber);
        qw.like(StringUtils.isNotBlank(contractNumber), "contractNumber", contractNumber);
        qw.like(StringUtils.isNotBlank(customerName), "customerName", customerName);

        // 产品相关查询（需要关联查询明细表，暂时保留）
        // TODO: 如果需要按产品查询，需要使用子查询或JOIN
        // qw.like(StringUtils.isNotBlank(productCode), "productCode", productCode);
        // qw.like(StringUtils.isNotBlank(productName), "productName", productName);

        // 状态查询
        if (StringUtils.isNotBlank(orderStatus)) {
            String finalDbStatus = OrderStatusMapper.isKnownDbStatus(orderStatus)
                    ? orderStatus
                    : OrderStatusMapper.engineToDb(OrderStatusMapper.toEngineState(orderStatus));
            qw.eq("orderStatus", finalDbStatus);
        }

        qw.eq(StringUtils.isNotBlank(urgencyLevel), "urgencyLevel", urgencyLevel);
        qw.eq(ObjectUtils.isNotEmpty(isCustomerSecret), "isCustomerSecret", isCustomerSecret);
        qw.ge(ObjectUtils.isNotEmpty(deliveryDateStart), "dueDate", deliveryDateStart);
        qw.le(ObjectUtils.isNotEmpty(deliveryDateEnd), "dueDate", deliveryDateEnd);
        qw.eq(ObjectUtils.isNotEmpty(createdBy), "createdBy", createdBy);
        qw.ge(ObjectUtils.isNotEmpty(createTimeStart), "createTime", createTimeStart);
        qw.le(ObjectUtils.isNotEmpty(createTimeEnd), "createTime", createTimeEnd);

        // 逻辑删除过滤
        qw.eq("is_deleted", 0);

        // 排序
        if (SqlUtils.validSortField(sortField)) {
            qw.orderBy(true, "ascend".equals(sortOrder), sortField);
        } else {
            qw.orderByDesc("createTime");
        }

        return qw;
    }

    @Override
    public SalesOrderVO getSalesOrderVO(SalesOrder salesOrder) {
        if (salesOrder == null) {
            return null;
        }

        SalesOrderVO vo = new SalesOrderVO();
        BeanUtils.copyProperties(salesOrder, vo);


        // 涉密信息脱敏
        if (salesOrder.getIsCustomerSecret() != null && salesOrder.getIsCustomerSecret() == 1) {
            vo.setCustomerName("***涉密客户***");
            vo.setCustomerContact("***涉密信息***");
        }

        // 查询订单明细
        if (salesOrder.getId() != null) {
            List<SalesOrderItem> items = salesOrderItemService.getByOrderId(salesOrder.getId());
            if (items != null && !items.isEmpty()) {
                List<SalesOrderItemVO> itemVOs = items.stream().map(item -> {
                    SalesOrderItemVO itemVO = new SalesOrderItemVO();
                    BeanUtils.copyProperties(item, itemVO);
                    return itemVO;
                }).collect(Collectors.toList());
                vo.setItems(itemVOs);
            }
        }

        return vo;
    }

    @Override
    public Page<SalesOrderVO> getSalesOrderVOPage(Page<SalesOrder> page) {
        List<SalesOrder> list = page.getRecords();
        Page<SalesOrderVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        if (list.isEmpty()) {
            return voPage;
        }

        // 批量查询订单明细（解决N+1问题）
        List<Long> orderIds = list.stream().map(SalesOrder::getId).collect(Collectors.toList());
        List<SalesOrderItem> allItems = salesOrderItemService.getByOrderIds(orderIds);

        // 按订单ID分组
        Map<Long, List<SalesOrderItem>> itemsMap = allItems.stream()
                .collect(Collectors.groupingBy(SalesOrderItem::getOrderId));

        // 组装VO
        List<SalesOrderVO> voList = list.stream().map(order -> {
            SalesOrderVO vo = new SalesOrderVO();
            BeanUtils.copyProperties(order, vo);

            // 涉密信息脱敏
            if (order.getIsCustomerSecret() != null && order.getIsCustomerSecret() == 1) {
                vo.setCustomerName("***涉密客户***");
                vo.setCustomerContact("***涉密信息***");
            }

            // 设置明细列表
            List<SalesOrderItem> items = itemsMap.get(order.getId());
            if (items != null && !items.isEmpty()) {
                List<SalesOrderItemVO> itemVOs = items.stream().map(item -> {
                    SalesOrderItemVO itemVO = new SalesOrderItemVO();
                    BeanUtils.copyProperties(item, itemVO);
                    return itemVO;
                }).collect(Collectors.toList());
                vo.setItems(itemVOs);
            }

            return vo;
        }).collect(Collectors.toList());

        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public SalesOrder getByOrderNumber(String orderNumber) {
        if (StringUtils.isBlank(orderNumber)) {
            return null;
        }
        return salesOrderMapper.selectByOrderNumber(orderNumber);
    }

    @Override
    public SalesOrder getByIdIncludeDeleted(Long id) {
        if (id == null) {
            return null;
        }
        QueryWrapper<SalesOrder> qw = new QueryWrapper<>();
        qw.eq("id", id);
        return this.baseMapper.selectOne(qw);
    }

    @Override
    public boolean updateOrderStatus(Long orderId, String newStatus, String currentNode, Double progress) {
        if (orderId == null || StringUtils.isBlank(newStatus)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "订单ID和新状态不能为空");
        }

        SalesOrder current = this.getById(orderId);
        if (current == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单不存在");
        }

        // 状态校验
        OrderStateEnum target;
        try {
            target = OrderStatusMapper.toEngineState(newStatus);
        } catch (IllegalArgumentException e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "非法状态: " + newStatus);
        }
        String dbStatus = OrderStatusMapper.engineToDb(target);

        // 更新订单
        SalesOrder upd = new SalesOrder();
        upd.setId(orderId);
        upd.setOrderStatus(dbStatus);
        upd.setCurrentNode(currentNode);
        if (progress != null) {
            upd.setProgress(BigDecimal.valueOf(progress));
        }

        return this.updateById(upd);
    }

    @Override
    public List<CountItemVO> getStatusStatistics(String orderType) {
        return salesOrderMapper.countByStatus(orderType);
    }

    @Override
    public List<CountItemVO> getUrgencyStatistics(String orderType) {
        return salesOrderMapper.countByUrgencyLevel(orderType);
    }

    @Override
    public List<SalesOrderVO> getUpcomingDeliveryOrders(Integer days, String orderType) {
        if (days == null || days <= 0) {
            days = 7;
        }
        List<SalesOrder> orders = salesOrderMapper.selectUpcomingDelivery(days, orderType);
        return orders.stream().map(this::getSalesOrderVO).collect(Collectors.toList());
    }

    @Override
    public List<SalesOrderVO> getOverdueOrders(String orderType) {
        List<SalesOrder> orders = salesOrderMapper.selectOverdueOrders(orderType);
        return orders.stream().map(this::getSalesOrderVO).collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createSalesOrder(SalesOrder salesOrder, List<SalesOrderItem> items) {
        // 设置订单类型
        salesOrder.setOrderType(OrderType.SALES.getCode());

        // 生成订单号
        String orderNumber = generateOrderNumber(OrderType.SALES);
        salesOrder.setOrderNumber(orderNumber);

        // 计算订单总金额（从明细汇总）
        calculateTotalAmount(salesOrder, items);

        // 设置默认状态
        setDefaultStatus(salesOrder);

        // 校验订单信息
        validSalesOrder(salesOrder, true, items);

        // 保存订单主表
        boolean saved = this.save(salesOrder);
        ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR, "保存订单失败");

        // 保存订单明细
        saveOrderItems(salesOrder.getId(), orderNumber, items);

//        // 发送Outbox消息
//        sendOrderCreatedMessage(salesOrder, items);

        log.info("销售订单创建成功: 订单ID={}, 订单号={}", salesOrder.getId(), orderNumber);
        return salesOrder.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRdoOrder(SalesOrder salesOrder, List<SalesOrderItem> items) {
        // 设置订单类型
        salesOrder.setOrderType(OrderType.RDO.getCode());

        // 生成订单号
        String orderNumber = generateOrderNumber(OrderType.RDO);
        salesOrder.setOrderNumber(orderNumber);

        // 计算订单总金额（从明细汇总）
        calculateTotalAmount(salesOrder, items);

        // 设置默认状态
        setDefaultStatus(salesOrder);

        // 校验订单信息
        validSalesOrder(salesOrder, true, items);

        // 保存订单主表
        boolean saved = this.save(salesOrder);
        ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR, "保存订单失败");

        // 保存订单明细
        saveOrderItems(salesOrder.getId(), orderNumber, items);

//        // 发送Outbox消息
//        sendOrderCreatedMessage(salesOrder, items);

        log.info("研发订单创建成功: 订单ID={}, 订单号={}", salesOrder.getId(), orderNumber);
        return salesOrder.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOrderWithItems(Long orderId, SalesOrder salesOrder,
                                        List<SalesOrderItem> items,
                                        List<Long> deleteAttachmentIds) {
        // 检查订单是否存在
        SalesOrder oldOrder = this.getById(orderId);
        if (oldOrder == null) {
            SalesOrder deletedOrder = this.getByIdIncludeDeleted(orderId);
            if (deletedOrder != null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,
                        String.format("订单已被删除，无法修改，订单号: %s", deletedOrder.getOrderNumber()));
            } else {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,
                        String.format("订单不存在，ID: %d", orderId));
            }
        }

        // 检查订单是否被软删除
        if (oldOrder.getIsDeleted() != null && oldOrder.getIsDeleted() == 1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "订单已被删除，无法修改");
        }

        // 如果提供了明细，重新计算订单总金额
        if (items != null && !items.isEmpty()) {
            calculateTotalAmount(salesOrder, items);
        }

        // 校验订单信息
        validSalesOrder(salesOrder, false, items);

        // 处理附件删除（常规逻辑：失败则抛出异常）
        if (deleteAttachmentIds != null && !deleteAttachmentIds.isEmpty()) {
            log.info("准备删除附件: 订单ID={}, 附件IDs={}", orderId, deleteAttachmentIds);
            boolean deleteResult = attachmentService.batchPhysicalDeleteAttachments(
                    deleteAttachmentIds,
                    salesOrder.getCreatedBy());
            if (!deleteResult) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "附件删除失败");
            }
        }

        // 更新订单主表
        salesOrder.setId(orderId);
        boolean result = this.updateById(salesOrder);

        // 更新订单明细
        if (items != null) {
            log.info("更新订单明细: 订单ID={}, 明细数量={}", orderId, items.size());
            boolean itemsResult = salesOrderItemService.updateOrderItems(
                    orderId, oldOrder.getOrderNumber(), items);
            if (!itemsResult) {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "更新订单明细失败");
            }
        }

        log.info("订单更新成功: 订单ID={}, 订单号={}", orderId, oldOrder.getOrderNumber());
        return result;
    }

    @Override
    public String getFirstProductName(Long orderId) {
        if (orderId == null) {
            return null;
        }
        List<SalesOrderItem> items = salesOrderItemService.getByOrderId(orderId);
        if (items != null && !items.isEmpty()) {
            return items.get(0).getProductName();
        }
        return null;
    }

    @Override
    public String getFirstProductCode(Long orderId) {
        if (orderId == null) {
            return null;
        }
        List<SalesOrderItem> items = salesOrderItemService.getByOrderId(orderId);
        if (items != null && !items.isEmpty()) {
            return items.get(0).getProductCode();
        }
        return null;
    }

    @Override
    public Integer getTotalQuantity(Long orderId) {
        if (orderId == null) {
            return null;
        }
        List<SalesOrderItem> items = salesOrderItemService.getByOrderId(orderId);
        if (items != null && !items.isEmpty()) {
            return items.stream()
                    .mapToInt(item -> item.getQuantity() != null ? item.getQuantity() : 0)
                    .sum();
        }
        return null;
    }

    // ==================== 私有辅助方法 ====================

    /**
     * 生成订单号
     */
    private String generateOrderNumber(OrderType orderType) {
        java.time.LocalDate now = java.time.LocalDate.now(java.time.ZoneId.of("Asia/Shanghai"));
        String dateKey = now.format(java.time.format.DateTimeFormatter.BASIC_ISO_DATE);

        Integer seq;
        if (orderType == OrderType.SALES) {
            salesOrderMapper.initSalesOrderSeqIfAbsent(dateKey);
            salesOrderMapper.incrSalesOrderSeq(dateKey);
            seq = salesOrderMapper.getLastInsertId();
        } else {
            salesOrderMapper.initRdoOrderSeqIfAbsent(dateKey);
            salesOrderMapper.incrRdoOrderSeq(dateKey);
            seq = salesOrderMapper.getLastInsertId();
        }

        if (seq == null || seq <= 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "生成订单号失败");
        }

        return orderType.getPrefix() + dateKey + String.format("%03d", seq);
    }

    /**
     * 计算订单总金额（从明细汇总）
     */
    private void calculateTotalAmount(SalesOrder salesOrder, List<SalesOrderItem> items) {
        if (items == null || items.isEmpty()) {
            return;
        }

        // 计算每个明细的金额（如果未设置）
        for (SalesOrderItem item : items) {
            if (item.getAmount() == null && item.getUnitPrice() != null && item.getQuantity() != null) {
                item.setAmount(item.getUnitPrice().multiply(BigDecimal.valueOf(item.getQuantity())));
            }
        }

        // 汇总总金额
        BigDecimal totalAmount = items.stream()
                .map(item -> item.getAmount() != null ? item.getAmount() : BigDecimal.ZERO)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 如果订单未设置总金额，使用计算值
        if (salesOrder.getTotalAmount() == null && totalAmount.compareTo(BigDecimal.ZERO) > 0) {
            salesOrder.setTotalAmount(totalAmount);
        }
    }

    /**
     * 设置默认状态
     */
    private void setDefaultStatus(SalesOrder salesOrder) {
        if (StringUtils.isBlank(salesOrder.getOrderStatus())) {
            salesOrder.setOrderStatus("CREATED");
            salesOrder.setCurrentNode("订单已创建");
            salesOrder.setProgress(BigDecimal.valueOf(0.00));
        }
    }

    /**
     * 保存订单明细
     */
    private void saveOrderItems(Long orderId, String orderNumber, List<SalesOrderItem> items) {
        if (items == null || items.isEmpty()) {
            return;
        }

        for (int i = 0; i < items.size(); i++) {
            SalesOrderItem item = items.get(i);
            item.setOrderId(orderId);
            item.setOrderNumber(orderNumber);
            item.setSortOrder(i);
            item.setId(null); // 确保是新增
        }

        boolean saved = salesOrderItemService.saveBatchItems(items);
        ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR, "保存订单明细失败");
    }

//    /**
//     * 发送订单创建消息（Outbox）
//     */
//    private void sendOrderCreatedMessage(SalesOrder salesOrder, List<SalesOrderItem> items) {
//        try {
//            Map<String, Object> payload = new HashMap<>();
//            payload.put("salesOrderId", salesOrder.getId());
//            payload.put("orderNumber", salesOrder.getOrderNumber());
//
//            // 使用第一个产品的名称
//            String productName = (items != null && !items.isEmpty())
//                    ? items.get(0).getProductName()
//                    : null;
//            payload.put("productName", productName);
//
//            payload.put("createdBy", salesOrder.getCreatedBy());
//            payload.put("createdByName", salesOrder.getCreatedByName());
//
//            outboxService.enqueue(null, "order.created", RabbitMqConfig.RK_ORDER_CREATED, payload);
//        } catch (Exception e) {
//            log.warn("发送订单创建消息失败: orderId={}", salesOrder.getId(), e);
//        }
//    }
}